using System;
using System.Collections;
using System.Collections.Generic;

namespace WindowsAPI.Hardware
{
    public class ClassDevicesList : IEnumerable<Device>, IEnumerable<SP_DEVINFO_DATA>
    {
        /* ------------------------------------------------------------------------------------------ */

        public Guid Guid { get; private set; }

        /* ------------------------------------------------------------------------------------------ */

        public ClassDevicesList(Guid Guid) { this.Guid = Guid; }

        /* ------------------------------------------------------------------------------------------ */

        IEnumerator<SP_DEVINFO_DATA> IEnumerable<SP_DEVINFO_DATA>.GetEnumerator() { return new ClassDevicesListEnumerator(Guid); }

        public IEnumerator<Device> GetEnumerator() { return new ClassDevicesListEnumerator(Guid); }

        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

        /* ------------------------------------------------------------------------------------------ */
    }

    public class ClassDevicesListEnumerator : IEnumerator<Device>, IEnumerator<SP_DEVINFO_DATA>
    {
        /* ------------------------------------------------------------------------------------------ */

        private SP_DEVINFO_DATA f_CurrentData;

        private int f_Index;

        /* ------------------------------------------------------------------------------------------ */

        public Guid Guid { get; private set; }

        public IntPtr Handle { get; private set; }

        object IEnumerator.Current { get { return Current; } }

        SP_DEVINFO_DATA IEnumerator<SP_DEVINFO_DATA>.Current { get { return f_CurrentData; } }
        public Device Current { get { return f_CurrentData.Device; } }

        /* ------------------------------------------------------------------------------------------ */

        public ClassDevicesListEnumerator(Guid ClassGuid)
        {
            Guid = ClassGuid;
            Handle = SetupAPI.SetupDiGetClassDevs(ref ClassGuid, null, IntPtr.Zero, DIGCF.Present | DIGCF.DeviceInterface);
        }

        /* ------------------------------------------------------------------------------------------ */

        public void Reset()
        {
            f_CurrentData = default(SP_DEVINFO_DATA);
            f_Index = 0;
        }

        public bool MoveNext()
        {
            f_CurrentData = SP_DEVINFO_DATA.Default;
            var sucsess = SetupAPI.SetupDiEnumDeviceInfo(Handle, f_Index, ref f_CurrentData);
            if(!sucsess) return false;
            f_Index++;
            return true;
        }

        /* ------------------------------------------------------------------------------------------ */

        public void Dispose() { SetupAPI.SetupDiDestroyDeviceInfoList(Handle); }

        /* ------------------------------------------------------------------------------------------ */
    }
}